home *** CD-ROM | disk | FTP | other *** search
/ Speccy ClassiX 1998 / Speccy ClassiX 98.iso / amiga_system / the_aminet / dev / gcc / ixemulsrc.lha / ixemul-41.4 / stdlib / ssystem.c < prev    next >
C/C++ Source or Header  |  1995-05-28  |  9KB  |  324 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Library General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Library General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Library General Public
  16.  *  License along with this library; if not, write to the Free
  17.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  22-jan-92    -mw-    restore sigmask before calling system()
  20.  */
  21.  
  22. #define KERNEL
  23. #include "ixemul.h"
  24. #include "kprintf.h"
  25. #include <ctype.h>
  26. #include <sys/wait.h>
  27.  
  28. /* 2.0 support */
  29. #include <utility/tagitem.h>
  30. #include <dos/dostags.h>
  31. #include <hardware/intbits.h>
  32.  
  33. #if __GNUC__ != 2
  34. #define alloca __builtin_alloca
  35. #endif
  36.  
  37. extern BPTR *__load_seg (char *name, char **args);
  38.  
  39. int
  40. ssystem(char *argline)
  41. {
  42.   int rc, err = 0;
  43.   UBYTE *arg, *index();
  44.   UBYTE *tmp;
  45.   int stack_size;
  46.   struct CommandLineInterface *CLI;
  47.   struct Process *me;
  48.   int omask;
  49.   void *old_trapdata, *old_trapcode;
  50.   int old_flags;
  51.   void *old_launch, *old_switch;
  52.  
  53.   omask = syscall (SYS_sigsetmask, ~0);
  54.   me = (struct Process *)FindTask(0);
  55.   CLI = BTOCPTR (me->pr_CLI);
  56.   stack_size = CLI ? CLI->cli_DefaultStack * 4 : me->pr_StackSize;
  57.   if (stack_size <= 4096) stack_size = 250000;
  58.  
  59.   /* the +1 is to get a cheap way to transform this into a BSTR */
  60.   tmp = alloca (strlen (argline) + 6);
  61.   tmp = LONG_ALIGN (tmp);
  62.   tmp++;
  63.  
  64.   strcpy (tmp, argline);
  65.  
  66.   while (*tmp == ' ' || *tmp == '\t') ++tmp;
  67.   /* not needed with custom load-seg function */
  68.  
  69.   if (arg = index(tmp, ' '))  *arg++ = 0;
  70.  
  71.     {
  72.       BPTR *segs;
  73.       char *args;
  74.       BPTR old_cis, old_cos, old_ces;
  75.       BPTR dup_cis, dup_cos, dup_ces;
  76.       struct file *f;
  77.  
  78.       segs = __load_seg (tmp, &args);
  79.  
  80.       /* check for special cookie */
  81.       if (segs == (BPTR *) -2)
  82.     {
  83.       syscall (SYS_sigsetmask, omask);
  84.  
  85.       /* let the shell do the dirty work ;-)) */
  86.       return system (argline);
  87.     }
  88.  
  89.       if (segs)
  90.     {
  91.       char **name;
  92.       char *orig;
  93.       char *all_args;
  94.       u_int old_signals;
  95.       
  96.       /* if __load_seg() set args to something, we have to rebuild our
  97.        * command line, but only just in that case ;-))
  98.        */
  99.       if (args)
  100.         {
  101.           int force_quotes = 0;
  102.  
  103.           /* now this IS a horrible kludge.. but again, I *NEED* sksh
  104.            * working, and it only works, if the argument to the -c 
  105.            * switch is passed quoted... So if the __load_seg code
  106.            * decided, that this was such a special sksh-script, it 
  107.            * negates the *arg parameter... shudder... 
  108.            *
  109.            * NOTE: This only works for command lines that contain no
  110.            *       quotes themselves... I don't escape the argument
  111.            *       line, I just put a pair of quotes around it!
  112.            *       The starting quote is already included in the args
  113.            *       string from __load_seg()...
  114.            */
  115.           if (((int)args) < 0)
  116.             {
  117.               force_quotes = 1;
  118.               args = (char *) ((-(int)args));
  119.             }
  120.  
  121.           /* make handling easier */
  122.           if (! arg) arg = "";
  123.           
  124.           /* the command we build looks like:
  125.            * <seg'd command> args arg
  126.            */
  127.           
  128.           all_args = alloca (strlen (args) + 1 + strlen (arg) + 4);
  129.           strcpy (all_args, args);
  130.           if (*arg)
  131.             {
  132.               strcat (all_args, " ");
  133.               strcat (all_args, arg);
  134.             }
  135.  
  136.           if (force_quotes)
  137.         strcat (all_args, "\"");  /* no comment... */
  138.           strcat (all_args, "\n");      /* neither, this insn't my kludge though.. */
  139.  
  140.           /* and finally reassign the commandline to arg */
  141.           arg = all_args;
  142.           /* if args was not "", we have to free it, it's from strdup() */
  143.           if (*args) syscall (SYS_free, args);
  144.         }
  145.       else
  146.         {    
  147.           /* even if we didn't get any arguments from the expander, we still
  148.            * need to protect the original arguments ala BCPL ..
  149.            * Remember that `arg' is a (large enough) alloca() string ;-) */
  150.           if (arg)
  151.         strcat (arg, "\n");
  152.           else
  153.         arg = "\n";
  154.         }
  155.  
  156.       /*
  157.        * Hack to always get the name of the currently executing program
  158.        * to show up in Xoper
  159.        */
  160.       if (CLI)
  161.         {
  162.           name = (char **) & CLI->cli_CommandName;
  163.           orig = *name;
  164.           /* that's why we incremented tmp before ;-)) */
  165.           ((unsigned char *)tmp)[-1] = strlen (tmp);
  166.           /* this is always odd (stack=even + 1), so will chop fine to BPTR */
  167.           *name = (char *) ((long)tmp >> 2);
  168.         }
  169.       else
  170.         {
  171.           name = (char **) & me->pr_Task.tc_Node.ln_Name;
  172.           orig = *name;
  173.           *name = tmp;
  174.         }
  175.  
  176.       KPRINTF (("RunCommand (stack_size=%ld, arg = >%s<, len = %ld)\n", stack_size, arg, strlen (arg)));
  177.       /* perform I/O redirection... (copied from execve.c) */
  178.  
  179.       if ((f = u.u_ofile[0]) && f->f_type == DTYPE_FILE)
  180.         {
  181.           dup_cis = 0;
  182.           old_cis = SelectInput (CTOBPTR (f->f_fh));
  183.           readargs_kludge (CTOBPTR (f->f_fh));
  184.           KPRINTF (("redir 0, old_cis = $%lx\n",old_cis));
  185.         }
  186.       else
  187.         {
  188.           if (!f)
  189.             {
  190.               int fd = open ("/dev/null", 0);
  191.               dup_cis = dup2_BPTR (fd);
  192.               close (fd);
  193.             }
  194.           else
  195.         dup_cis = dup2_BPTR (0);
  196.           old_cis = 0;
  197.           if (dup_cis)
  198.             {
  199.               old_cis = SelectInput (dup_cis);
  200.               readargs_kludge (dup_cis);
  201.           KPRINTF (("redir 0, old_cis = $%lx, dup_cis = $%lx\n", old_cis, dup_cis));
  202.             }
  203.           else
  204.         KPRINTF (("redir 0, dup2_BPTR failed\n"));
  205.         }
  206.  
  207.       if ((f = u.u_ofile[1]) && f->f_type == DTYPE_FILE)
  208.         {
  209.           dup_cos = 0;
  210.           old_cos = SelectOutput (CTOBPTR (f->f_fh));
  211.           KPRINTF (("redir 1, old_cos = $%lx\n", old_cos));
  212.         }
  213.       else
  214.         {
  215.           if (!f)
  216.             {
  217.               int fd = open ("/dev/null", 1);
  218.               dup_cos = dup2_BPTR (fd);
  219.               close (fd);
  220.             }
  221.           else
  222.             dup_cos = dup2_BPTR (1);
  223.           old_cos = 0;
  224.           if (dup_cos)
  225.             {
  226.               old_cos = SelectOutput (dup_cos);
  227.               KPRINTF (("redir 1, old_cos = $%lx, dup_cos = $%lx\n", old_cos, dup_cos));
  228.             }
  229.           else
  230.             KPRINTF (("redir 1, dup2_BPTR failed\n"));
  231.         }
  232.       old_ces = me->pr_CES;
  233.       if ((f = u.u_ofile[2]) && f->f_type == DTYPE_FILE)
  234.         {
  235.           dup_ces = 0;
  236.           me->pr_CES = CTOBPTR (f->f_fh);
  237.         }
  238.           else
  239.         {
  240.           if (!f)
  241.             {
  242.               int fd = open ("/dev/null", 2);
  243.               dup_ces = dup2_BPTR (fd);
  244.               close (fd);
  245.             }
  246.           else
  247.             dup_ces = dup2_BPTR (2);
  248.           me->pr_CES = dup_ces ? : old_ces;
  249.         }
  250.  
  251.       /* cleanup as much of ixemul.library as possible, so that the started
  252.          process can take over */
  253.       old_flags             = me->pr_Task.tc_Flags;
  254.       me->pr_Task.tc_Flags  = u_save.u_otask_flags;
  255.       old_launch            = me->pr_Task.tc_Launch;
  256.       me->pr_Task.tc_Launch = u_save.u_olaunch; /* restoring this disables our signals */
  257.       old_switch            = me->pr_Task.tc_Switch;
  258.       me->pr_Task.tc_Switch = u_save.u_oswitch;
  259.       RemIntServer (INTB_VERTB, & u_save.u_itimerint);
  260.  
  261.       /* BEWARE that after this reset no library functions can be
  262.          called any longer until the moment where trapdata is 
  263.          reinstalled !! */
  264.       old_trapdata = me->pr_Task.tc_TrapData;
  265.       me->pr_Task.tc_TrapData = u_save.u_otrap_data;
  266.       old_trapcode = me->pr_Task.tc_TrapCode;
  267.       me->pr_Task.tc_TrapCode = u_save.u_otrap_code;
  268.  
  269.       /* RunCommand should provide the started program with a fresh set of
  270.        * signals, it doesn't. So we do this by hand here... */
  271.       old_signals = me->pr_Task.tc_SigAlloc;
  272.       me->pr_Task.tc_SigAlloc &= 0xffff;
  273.  
  274.       rc = RunCommand (*segs, stack_size, arg, strlen (arg));
  275.  
  276.       me->pr_Task.tc_TrapData = old_trapdata;
  277.       me->pr_Task.tc_TrapCode = old_trapcode;
  278.  
  279.       KPRINTF (("RunCommand back, stack_size = %ld, rc = %ld, sp = $%lx\n", stack_size, rc, get_sp()));
  280.  
  281.       me->pr_Task.tc_SigAlloc = old_signals;
  282.           err = __ioerr_to_errno (IoErr ());
  283.       *name = orig;
  284.  
  285.       AddIntServer (INTB_VERTB, & u_save.u_itimerint);
  286.       me->pr_Task.tc_Launch = old_launch;
  287.       me->pr_Task.tc_Switch = old_switch;
  288.       me->pr_Task.tc_Flags  = old_flags;
  289.  
  290.       if (old_cis)
  291.         SelectInput (old_cis);
  292.       if (old_cos)
  293.         SelectOutput (old_cos);
  294.       me->pr_CES = old_ces;
  295.  
  296.       /* reset I/O */
  297.       if (dup_cis)
  298.         Close (dup_cis);
  299.           if (dup_cos)
  300.             Close (dup_cos);
  301.           if (dup_ces)
  302.             Close (dup_ces);
  303.  
  304.       __free_seg (segs);
  305.     }
  306.       else
  307.     {
  308.       rc = 20;
  309.  
  310.           err = __ioerr_to_errno (IoErr ());
  311.         }
  312.     }
  313.  
  314.   syscall (SYS_sigsetmask, omask);
  315.  
  316.   if (rc > 128)
  317.     errno = EINTR;
  318.   else
  319.     errno = err;
  320.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  321.  
  322.   return (rc >= 128) ? W_EXITCODE (0, rc & 0x7f) : W_EXITCODE (rc, 0);
  323. }
  324.